package com.serviceImpl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.domain.*;
import com.domainVO.CommentUserVO;
import com.domainVO.IssueUserLabeCommentlVO;
import com.domainVO.PageInfoVO;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mapper.helping.*;
import com.mapper.living.UserDao;
import com.qiniu.common.QiniuException;
import com.service.IIssueCommentService;
import com.service.IIssueService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.service.ILabelWithIssueService;
import com.service.living.OfficialMessageService;
import com.util.HotUtil;
import com.util.QiNiuYunUtils;
import com.util.UserUtil;
import living.com.domain.OfficialMessageType;
import living.com.domain.User;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 大忽悠
 * @since 2022年02月08日
 */
@RequiredArgsConstructor
@Service
@Transactional(value = "primaryTransactionManager")
public class IssueServiceImpl extends ServiceImpl<IssueMapper, Issue> implements IIssueService {

    private final IssueMapper issueMapper;
    private final UserDao userDaol;
    private final LabelMapper labelMapper;
    private final ILabelWithIssueService iLabelWithIssueService;
    private final UserLikeWithIssueMapper userLikeWithIssueMapper;
    private final IssueCommentMapper issueCommentMapper;
    private  final QiNiuYunUtils qiNiuYunUtils;
    private final IIssueCommentService iIssueCommentService;
    private static final ObjectMapper objectMapper=new ObjectMapper();
    private final HotUtil hotUtil;
    private final OfficialMessageService officialMessageService;
    /**
     * 通用问题图片和视频路径处理方法
     */
    private void commonIssuePathHandle(Issue issue) throws JsonProcessingException {
        if(issue.getImgs()!=null&&!issue.getImgs().equals("")&&!issue.getImgs().equals("[]")) {
            List<String> list = objectMapper.readValue(issue.getImgs(), List.class);
            list=list.stream().map(x->qiNiuYunUtils.getFilePrefix()+x).collect(Collectors.toList());
            issue.setImgPaths(list);
        }issue.setImgs(null);

        if(issue.getVideos()!=null&&!issue.getVideos().equals("")&&!issue.getVideos().equals("[]")) {
            List<String> list = objectMapper.readValue(issue.getVideos(), List.class);
            list=list.stream().map(x->qiNiuYunUtils.getFilePrefix()+x).collect(Collectors.toList());
            issue.setVideoPaths(list);
        }issue.setVideos(null);
    }

    private void commonCommentPathHandle(IssueComment comment) throws JsonProcessingException {
        if(comment.getImgs()!=null&&!comment.getImgs().equals("")&&!comment.getImgs().equals("[]")) {
            List<String> list =objectMapper.readValue(comment.getImgs(), List.class);
            list=list.stream().map(x->qiNiuYunUtils.getFilePrefix()+x).collect(Collectors.toList());
            comment.setImgPaths(list);
        }comment.setImgs(null);
        if(comment.getVideos()!=null&&!comment.getVideos().equals("")&&!comment.getVideos().equals("[]")) {
            List<String> list = objectMapper.readValue(comment.getVideos(), List.class);
            list=list.stream().map(x->qiNiuYunUtils.getFilePrefix()+x).collect(Collectors.toList());
            comment.setVideoPaths(list);
        }comment.setVideos(null);
    }

    /**
     * 问题查询通用处理方法
     */
    public void commonSearchOpeartion(List<Issue> issues,Collection<IssueUserLabeCommentlVO> res,boolean withUser)
    {
        AtomicBoolean isThrow= new AtomicBoolean(false);
        //过滤掉被隐式删除的问题
        issues.stream().filter(issue -> issue.getIsDeleted()==0).forEach(issue -> {
            //当前问题访问量加一
            issue.setViews(issue.getViews()+1);
            issueMapper.updateById(issue);
            try {
                //设置问题路径
                commonIssuePathHandle(issue);
            } catch (JsonProcessingException e) {
             isThrow.set(true);
            }
            //查询出每个问题对应的所有标签,加入对应的标签集合
        List<Label> labels=labelMapper.listAllLabelsWithTargetIssue(issue.getId());
        IssueUserLabeCommentlVO issueUserLabeCommentlVO = IssueUserLabeCommentlVO.builder().issue(issue).label(labels).build();
        //当前用户是否给当前问题点赞了
        UserLikeWithIssue one = userLikeWithIssueMapper.selectOne(new QueryWrapper<UserLikeWithIssue>()
                .eq("user_id", UserUtil.getUserId()).eq("issue_id", issue.getId()));
        issueUserLabeCommentlVO.setIsLike(one!=null?1:0);
        //判断问题是否是匿名发布的
        if(withUser&&issue.getIsAnony()==0)
        {
            //不是匿名发布的，设置用户，否则不返回用户
            issueUserLabeCommentlVO.setUser(userDaol.publishWithAttention(issue.getUserId(),UserUtil.getUserId()));
        }
        //查询当前问题对应的热门回答
        List<IssueComment> issueComments = issueCommentMapper.selectList(new QueryWrapper<IssueComment>().eq("issue_id", issue.getId())
                .orderByDesc(Arrays.asList("like_sum", "response_sum", "id")));
        if(issueComments==null || issueComments.size()==0)
        {
            res.add(issueUserLabeCommentlVO);
        }
        else
        {
            User publisher = userDaol.publishWithAttention(issueComments.get(0).getUserId(),UserUtil.getUserId());
            IssueComment issueComment=null;
            for (IssueComment ic : issueComments) {
                //当前热门回答是否被删除了,如果被删除了,就下一个，没有下一个返回null
                if(ic.getIsDeleted()!=1)
                {
                    issueComment=ic;
                    try {
                        commonCommentPathHandle(issueComment);
                    } catch (JsonProcessingException e) {
                        isThrow.set(true);
                    }
                    issueUserLabeCommentlVO.setCommentUserVO(CommentUserVO.builder().issueComment(issueComment)
                            .user(publisher).build());
                     break;
                }
            }
            res.add(issueUserLabeCommentlVO);
        }
    });
    if(isThrow.get())
    {
        throw new IllegalArgumentException("序列化异常");
    }
    }


    @Override
    public Map<String, Object> getAllQuestionsByTime(Integer startPage, Integer pageSize) {
        Page<Issue> page=new Page<>(startPage,pageSize);
        //按照时间排序
        Page<Issue> issues = issueMapper.selectPage(page, new QueryWrapper<Issue>().orderByDesc("id"));
        //key:问题id ,value:返回给前端的数据
        List<IssueUserLabeCommentlVO> res=new ArrayList<>();
        commonSearchOpeartion(issues.getRecords(),res,true);
        return PageInfoVO.builder().autoWired(page,res);
    }

    @Override
    public Map<String, Object> getAllQuestionsByHot(Integer startPage, Integer pageSize) {
        Page<Issue> page=new Page<>(startPage,pageSize);
        //按照热度排序
        Page<Issue> issues = issueMapper.selectPage(page, new QueryWrapper<Issue>()
                .orderByDesc(Arrays.asList("hot","like_sum","views","comment_sum","update_time")));
        //key:问题id ,value:返回给前端的数据
        List<IssueUserLabeCommentlVO> res=new ArrayList<>();
        commonSearchOpeartion(issues.getRecords(),res,true);
        return PageInfoVO.builder().autoWired(page,res);
    }

    /**
     * <p>
     *     获取未审核的问题
     * </p>
     * @param startPage
     * @param pageSize
     * @return
     */
    @Override
    public Map<String, Object> getUnauditIssue(Integer startPage, Integer pageSize) throws JsonProcessingException {
        Page<Issue> page=new Page<>(startPage,pageSize);
        List<Issue> issues = issueMapper.selectPage(page, new QueryWrapper<Issue>().
                eq("is_audited", 0).orderByDesc("id")).getRecords();
        //通用路径处理
        for (Issue issue : issues) {
            commonIssuePathHandle(issue);
        }
        return PageInfoVO.builder().autoWired(page,issues);
    }

    /**
     * <P>
     *     问题通过审核
     * </P>
     * @param issue_id
     * @return
     */
    @Override
    public Boolean passIssue(Integer issue_id) {
        return issueMapper.passIssue(issue_id);
    }


    @Override
    public IssueUserLabeCommentlVO getTargetIssue(Integer issue_id) throws JsonProcessingException {
        Issue issue = issueMapper.selectById(issue_id);
        //判断问题是否存在
        Assert.isTrue(issue!=null&&issue.getIsDeleted()==0,"问题不存在");
        //当前问题访问量加一
        issue.setViews(issue.getViews()+1);
        //更新访问量到数据库
        issueMapper.updateById(issue);
        //设置路径
        commonIssuePathHandle(issue);
        //查询问题对应的所有标签,加入对应的标签集合
        List<Label> labels=labelMapper.listAllLabelsWithTargetIssue(issue.getId());
        IssueUserLabeCommentlVO issueUserLabeCommentlVO = IssueUserLabeCommentlVO.builder().issue(issue).label(labels).build();
        //当前用户是否给当前问题点赞了
        UserLikeWithIssue one = userLikeWithIssueMapper.selectOne(new QueryWrapper<UserLikeWithIssue>()
                .eq("user_id", UserUtil.getUserId()).eq("issue_id", issue.getId()));
        issueUserLabeCommentlVO.setIsLike(one!=null?1:0);
        //判断问题是否是匿名发布的
        if(issue.getIsAnony()==0)
        {
            //不是匿名发布的，设置用户，否则不返回用户
            issueUserLabeCommentlVO.setUser(userDaol.publishWithAttention(issue.getUserId(),UserUtil.getUserId()));
        }
        //查询当前问题对应的热门回答
        List<IssueComment> issueComments = issueCommentMapper.selectList(new QueryWrapper<IssueComment>().eq("issue_id", issue.getId())
                .orderByDesc(Arrays.asList("like_sum", "response_sum", "id")));
        if(issueComments==null || issueComments.size()==0)
        {
            return issueUserLabeCommentlVO;
        }
        else
        {
            //对热门回答进行路径处理
            IssueComment issueComment=null;
            for (IssueComment ic : issueComments) {
                //当前热门回答是否被删除了,如果被删除了,就下一个，没有下一个返回null
                if(ic.getIsDeleted()!=1)
                {
                    issueComment=ic;
                    commonCommentPathHandle(issueComment);
                    User publisher = userDaol.publishWithAttention(issueComment.getUserId(),UserUtil.getUserId());
                    issueUserLabeCommentlVO.setCommentUserVO(CommentUserVO.builder().issueComment(issueComment)
                            .user(publisher).build());
                    break;
                }
            }
            return issueUserLabeCommentlVO;
        }
    }

    @Override
    public Map<String, Object> vagueSearchQuestions(String keyWord, Integer startPage, Integer pageSize) {
        Page<Issue> page=new Page<>(startPage,pageSize);
        //按照问题标题进行模糊查询
        Page<Issue> issues = issueMapper.selectPage(page, new QueryWrapper<Issue>()
                .like("question_title",keyWord).orderByDesc(Arrays.asList("like_sum","hot","comment_sum","views","update_time")));
        //key:问题id ,value:返回给前端的数据
        Set<IssueUserLabeCommentlVO> res1=new HashSet<>();
       commonSearchOpeartion(issues.getRecords(),res1,true);

        //按照标签内容进行模糊查询
        Page<Issue> page1=new Page<>(startPage,pageSize);
        List<Issue> issues1 = labelMapper.selectVagueByLabelContent(page1,keyWord);
        //被搜索出来的标签热度增加
        List<Label> labels = labelMapper.selectList(new QueryWrapper<Label>().like("content", keyWord));
        labels.forEach(x->{
            x.setHot(x.getHot()+hotUtil.getLABEL_LIKE_HOT_ADD());
            labelMapper.updateById(x);
        });
        commonSearchOpeartion(issues1,res1,true);
        return PageInfoVO.builder().autoWired(page1,res1);
    }

    /**
     * <p>
     *     删除问题对应的所有映射关系
     *     1.问题和标签的映射
     *     2.问题和点赞的映射
     *     5.删除问题关联的图片和视频资源
     *     3.问题下面所有的评论
     *     4.调用删除每个子评论的接口
     * </p>
     */
    @Override
    public Boolean delTargetQuestion(Integer issue_id) throws QiniuException, JsonProcessingException {
        //0.判断是否是问题发布者自己删除了问题
        boolean res = issueMapper.selectById(issue_id).getUserId().equals(UserUtil.getUserId());
        Assert.isTrue(res,"无权删除");
        //查找当前问题下的所有父评论
        List<Integer> issueCommentIds = issueCommentMapper.selectList(new QueryWrapper<IssueComment>()
                .eq("issue_id", issue_id)).stream().map(x -> x.getId()).collect(Collectors.toList());
        for (Integer issueCommentId : issueCommentIds) {
            iIssueCommentService.delTargetComment(issueCommentId);
        }
        //1.删除问题和标签的映射
        HashMap<String,Object> paramsMap = new HashMap<>();
        paramsMap.put("issue_id",issue_id);
        boolean res1 = iLabelWithIssueService.removeByMap(paramsMap);
        //2.删除问题和点赞的映射
        HashMap<String,Object> paramsMap1 = new HashMap<>();
        paramsMap1.put("issue_id",issue_id);
        userLikeWithIssueMapper.deleteByMap(paramsMap1);
        //删除问题关联的图片和视频
        Issue issue = issueMapper.selectById(issue_id);
        String imgs = issue.getImgs();
        if(imgs!=null)
        {
            List<String> list = objectMapper.readValue(imgs, List.class);
            for (String imgPath : list) {
                qiNiuYunUtils.deleteFile(imgPath);
            }
        }
        String videos = issue.getVideos();
        if(videos!=null)
        {
            List<String> list = objectMapper.readValue(videos, List.class);
            for (String videoPath : list) {
                qiNiuYunUtils.deleteFile(videoPath);
            }
        }
        //删除问题本身的记录
        int finallyRes = issueMapper.deleteById(issue_id);
       return res1 && (finallyRes==1) ;
    }

    @Override
    public boolean likeAdd(Integer issue_id, int num) {
        return issueMapper.likeAdd(issue_id,num);
    }

    @Override
    public Map<String,Object> getOwnIssues(Integer startPage,Integer pageSize) {
        Page<Issue> page=new Page<>(startPage,pageSize);
        Page<Issue> issues = issueMapper.selectPage(page, new QueryWrapper<Issue>()
                .eq("user_id",UserUtil.getUserId()).orderByDesc("hot"));
        //key:问题id ,value:返回给前端的数据
        List<IssueUserLabeCommentlVO> res=new ArrayList<>();
         commonSearchOpeartion(issues.getRecords(),res,false);
        return PageInfoVO.builder().autoWired(page,res);
    }

    @Override
    public Map<String, Object> getMyLikeIssues(Integer startPage,Integer pageSize) {
        Page<UserLikeWithIssue> page=new Page<>(startPage,pageSize);
        List<Integer> issueIds = userLikeWithIssueMapper.selectPage(page, new QueryWrapper<UserLikeWithIssue>()
                        .eq("user_id", UserUtil.getUserId())).getRecords()
                .stream().map(userLikeWithIssue -> userLikeWithIssue.getIssueId()).collect(Collectors.toList());
        List<Issue> issues = issueMapper.selectBatchIds(issueIds);
        //问题按照热度排序
        issues.sort((i1,i2)->-i1.getHot()+i2.getHot());
        List<IssueUserLabeCommentlVO> res=new ArrayList<>();
        commonSearchOpeartion(issues,res,true);
        return PageInfoVO.builder().autoWired(page,res);
    }

    @Override
    public Boolean logicDelTargetQuestion(Integer issue_id) {
        //只有自己才能删除自己发布的问题
        Issue issue = issueMapper.selectById(issue_id);
        Assert.isTrue(issue.getUserId().equals(UserUtil.getUserId()),"无权删除问题");
        Boolean res=issueMapper.logicDelTargetQuestion(issue_id);
        return res;
    }

    @Override
    public Boolean backLogicDelIssue(Integer issue_id, String reason) {
        Issue issue = issueMapper.selectById(issue_id);
        Assert.notNull(issue,"问题不存在");
        Boolean res=issueMapper.logicDelTargetQuestion(issue_id);
        //发送官方消息
        officialMessageService.sendOfficialMessage("您的问题已被管理员删除,原因:" + reason, null, issue.getUserId(),
                OfficialMessageType.PUNISH);
        return res;
    }


    @Override
    public Boolean WeiXinDel(Integer issue_Id) {
        return issueMapper.logicDelTargetQuestion(issue_Id);
    }
}
